package com.itxuhang.mapping;

import com.itxuhang.annotation.Controller;
import com.itxuhang.annotation.RequestMapping;
import com.itxuhang.handler.HandlerMethod;
import com.itxuhang.springframework.aware.BeanFactoryAware;
import com.itxuhang.springframework.factory.DefaultListableBeanFactory;
import com.itxuhang.springframework.init.InitializingBean;
import com.itxuhang.springframework.po.BeanDefinition;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RequestMappingHandlerMapping implements HandlerMapping, InitializingBean, BeanFactoryAware {
    // key就是URL，value就是HandlerMethod对象
    private Map<String, HandlerMethod> urlHandlerMethods = new HashMap<>();
    private DefaultListableBeanFactory beanFactory;

    @Override
    public Object getHandler(HttpServletRequest request) {
        String uri = request.getRequestURI();
        if (uri == null || "".equals(uri)){
            return null;
        }
        return this.urlHandlerMethods.get(uri);
    }

    @Override
    public void afterPropertiesSet() {
        List<BeanDefinition> beanDefinitions = beanFactory.getBeanDefinitions();
        for (BeanDefinition bd : beanDefinitions) {
            Class<?> clazzType = bd.getClassType();
            String beanName = bd.getBeanName();
            if(isHandler(clazzType)){
                RequestMapping clazzRequestMapping = clazzType.getAnnotation(RequestMapping.class);
                String classUrl = clazzRequestMapping.value();

                Method[] methods = clazzType.getDeclaredMethods();
                for (Method method : methods) {
                    if(method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
                        String methodUrl = methodRequestMapping.value();


                        String url = combine(classUrl,methodUrl);

                        HandlerMethod hm = new HandlerMethod(beanFactory.getBean(beanName),method);
                        this.urlHandlerMethods.put(url,hm);
                    }
                }
            }
        }
    }

    private String combine(String clazzUrl, String methodUrl) {

        if (clazzUrl != null && !"".equals(clazzUrl) && !clazzUrl.startsWith("/")){
            clazzUrl = "/"+clazzUrl;
        }
        if (!methodUrl.startsWith("/")){
            methodUrl = "/"+methodUrl;
        }
        StringBuffer sb = new StringBuffer();
        return sb.append(clazzUrl).append(methodUrl).toString();
    }

    private boolean isHandler(Class<?> clazzType) {
        return clazzType.isAnnotationPresent(Controller.class)
                || clazzType.isAnnotationPresent(RequestMapping.class);
    }

    @Override
    public void setBeanFactory(DefaultListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
}
